package com.net.okhttphelper;

import android.text.TextUtils;

import com.net.okhttphelper.download.CommonDownloadCallBack;
import com.net.okhttphelper.download.DownloadListener;
import com.net.okhttphelper.http.CommonCallBack;
import com.net.okhttphelper.http.DataCallBack;
import com.net.okhttphelper.http.HttpConfig;
import com.net.okhttphelper.http.HttpRequest;
import com.net.okhttphelper.http.RequestParams;
import com.net.okhttphelper.interceptor.ProgressInterceptor;
import com.net.okhttphelper.upload.UploadListener;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Dispatcher;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.logging.HttpLoggingInterceptor;

/**
 * 封装一个OkHttp请求工具类
 * 注意：要先调用 init 方法，不然报空指针
 * @author jie
 */
public class OkHttpHelper {

    private static OkHttpHelper instance = null;
    private OkHttpClient mOkHttpClient;
    private HttpConfig mHttpConfig;

    private OkHttpHelper(){
    }

    public static OkHttpHelper getInstance() {
        if (instance == null){
            synchronized (OkHttpHelper.class){
                instance = new OkHttpHelper();
            }
        }
        return instance;
    }

    /**
     * 初始话OkHttpClient
     * @param httpConfig 网络请求配置实体
     */
    public void init(HttpConfig httpConfig){
        this.mHttpConfig = httpConfig;
        mOkHttpClient = okHttpClientBuild(httpConfig);
    }

    /**
     * 执行一个请求，不带上传进度监听的
     * @param requestParams 请求参数
     * @param callBack 请求回调
     */
    public void enqueue(RequestParams requestParams, DataCallBack callBack){
        enqueue(requestParams, callBack, null);
    }

    /**
     * 执行一个请求,带上传进度监听
     * @param requestParams 请求参数
     * @param callBack 请求回调
     * @param uploadListener 上传监听
     */
    public void enqueue(RequestParams requestParams, DataCallBack callBack, UploadListener uploadListener){
        Call call = createCall(requestParams, uploadListener, null);
        call.enqueue(new CommonCallBack(callBack));
    }

    /**
     * 下载文件
     * @param requestParams 下载参数
     * @param callBack 请求回调
     * @param downloadListener 下载进度监听，可以为空
     */
    public void download(RequestParams requestParams, DataCallBack callBack, DownloadListener downloadListener){
        Call call = createCall(requestParams,null, downloadListener);
        String saveDirPath = getSaveDirPath(requestParams.getSaveDirPath());
        call.enqueue(new CommonDownloadCallBack(saveDirPath, callBack));
    }

    /**
     * 根据请求参数创建一个Call对象
     */
    private Call createCall(RequestParams requestParams, UploadListener uploadListener, DownloadListener downloadListener) {
        if (mOkHttpClient == null) {
            throw new NullPointerException("OkHttpHelper未初始化！");
        }
        Request request = HttpRequest.createRequest(requestParams, mHttpConfig.getBaseUrl(), uploadListener, downloadListener);
        return mOkHttpClient.newCall(request);
    }

    /**
     * 取消一个网络请求
     * @param tag 请求标识
     */
    public void cancel(String tag){
        if (mOkHttpClient == null) {
            return;
        }
        Dispatcher dispatcher = mOkHttpClient.dispatcher();
        List<Call> queuedCalls = dispatcher.queuedCalls();
        List<Call> runningCalls = dispatcher.runningCalls();
        cancel(queuedCalls, tag);
        cancel(runningCalls, tag);
    }

    /**
     * 取消一个网络请求
     */
    private void cancel(List<Call> calls, String tag){
        if (calls != null && (!calls.isEmpty())){
            for (Call call : calls) {
                if (Objects.equals(call.request().tag(), tag)){
                    call.cancel();
                }
            }
        }
    }

    /**
     * 取消所有网络请求
     */
    public void cancelAll(){
        if (mOkHttpClient == null) {
            return;
        }
        Dispatcher dispatcher = mOkHttpClient.dispatcher();
        dispatcher.cancelAll();
    }

    /**
     * 根据传递进来的参数构建OkHttpClient对象
     */
    private OkHttpClient okHttpClientBuild(HttpConfig httpConfig){
        if (httpConfig == null) {
            throw new NullPointerException("httpConfig不能为空！");
        }
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        // 添加日志打印拦截器
        if (httpConfig.isShowLog()){
            //打印请求Log
            HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(/*new HttpLoggingInterceptor.Logger() {
                @Override
                public void log(String message) {
                    LogUtils.w(message);
                }
            }*/);
            interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(interceptor);
        }
        // 添加进度拦截器
        builder.addNetworkInterceptor(ProgressInterceptor.build());
        long readTime = httpConfig.getReadTimeout();
        long connectTime = httpConfig.getConnectTimeout();
        return builder
                .retryOnConnectionFailure(true)
                .readTimeout(readTime, TimeUnit.MILLISECONDS)
                .connectTimeout(connectTime, TimeUnit.MILLISECONDS)
                .build();
    }

    /**
     * 获取文件下载存储文件夹地址
     * @param saveDirPath 用户自定义的文件存储地址
     */
    private String getSaveDirPath(String saveDirPath) {
        if (TextUtils.isEmpty(saveDirPath)){
            saveDirPath = mHttpConfig.getSaveFilePath();
        }
        return saveDirPath;
    }
}
